package ru.spb.osll.myfit.server.parser;

import static org.junit.Assert.assertEquals;

import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;

import ru.spb.osll.myfit.common.Include;
import ru.spb.osll.myfit.common.Page;
import ru.spb.osll.myfit.common.PageElement;
import ru.spb.osll.myfit.common.PageElementType;
import ru.spb.osll.myfit.common.Table;
import ru.spb.osll.myfit.common.TableStyle;
import ru.spb.osll.myfit.common.WikiText;
import ru.spb.osll.myfit.server.Converter;
import ru.spb.osll.myfit.util.CollectionUtils;

public class PageParserTest {

	private PageParser m_parser;
	private Converter converter;

	@Before
	public void setUp() {
		converter = EasyMock.createMock(Converter.class);
		m_parser = new PageParser(converter);
	}

	@Test
	public void testParsePage() {
		List<PageElement> elements = m_parser.parsePage(CollectionUtils.list(
				"|enable advanced retention on clusters|",
				PageParser.LINE_SEPARATOR, "|with cubetools|",
				"|write|10|files of size|10KB|using|10|threads|",
				PageParser.LINE_SEPARATOR, "!include .TestPage"));
		assertEquals(3, elements.size());
		Table first = (Table) elements.get(0);
		Table second = (Table) elements.get(1);
		checkTables(first, second);
		Include include = (Include) elements.get(2);
		assertEquals(".TestPage", include.getPath());

	}

	@Test
	public void testWikiParser() {
		String wiki = "[[.Text]]";
		String html = "<a href=\".Text\">.Text</a>";
		EasyMock.expect(converter.convertWikiToHtml(wiki)).andReturn(html);
		EasyMock.replay(converter);
		m_parser = new PageParser(converter);

		List<PageElement> elements = m_parser.parsePage(CollectionUtils.list(
				"|enable advanced retention on clusters|",
				PageParser.LINE_SEPARATOR, wiki, PageParser.LINE_SEPARATOR,
				"|with cubetools|",
				"|write|10|files of size|10KB|using|10|threads|"));

		assertEquals(3, elements.size());
		assertEquals(PageElementType.TABLE, elements.get(0).getType());
		assertEquals(PageElementType.WIKI_TEXT, elements.get(1).getType());
		WikiText wikiText = (WikiText) elements.get(1);
		assertEquals(wiki, wikiText.getWikiText());
		assertEquals(html, wikiText.getHtmlText());
		EasyMock.verify(converter);

	}

	@Test
	public void testWikiParser2() {
		String wiki = "[[.Text]]";
		String html = "<a href=\".Text\">.Text</a>";
		EasyMock.expect(converter.convertWikiToHtml(wiki)).andReturn(html);
		EasyMock.replay(converter);
		m_parser = new PageParser(converter);

		List<PageElement> elements = m_parser.parsePage(CollectionUtils.list(
				"|enable advanced retention on clusters|",
				PageParser.LINE_SEPARATOR, "!include .Test",
				PageParser.LINE_SEPARATOR, wiki, PageParser.LINE_SEPARATOR,
				"|with cubetools|",
				"|write|10|files of size|10KB|using|10|threads|"));

		assertEquals(4, elements.size());
		assertEquals(PageElementType.WIKI_TEXT.getKey(), elements.get(2)
				.getType().getKey());
		WikiText wikiText = (WikiText) elements.get(2);
		assertEquals(wiki, wikiText.getWikiText());
		assertEquals(html, wikiText.getHtmlText());
		EasyMock.verify(converter);

	}

	@Test
	public void testParsePageWithInclude1() {
		List<PageElement> elements = m_parser.parsePage(CollectionUtils.list(
				"|enable advanced retention on clusters|",
				PageParser.LINE_SEPARATOR, "!include .TestPage",
				PageParser.LINE_SEPARATOR, "|with cubetools|",
				"|write|10|files of size|10KB|using|10|threads|"));

		assertEquals(3, elements.size());
		assertEquals(PageElementType.INCLUDE.getKey(), elements.get(1)
				.getType().getKey());
		Include include = (Include) elements.get(1);
		assertEquals(".TestPage", include.getPath());
	}

	@Test
	public void testParsePageWithInclude2() {
		// TODO: this test fail. Problem in the parser.
		List<PageElement> elements = m_parser.parsePage(CollectionUtils.list(
				"|enable advanced retention on clusters|",
				PageParser.LINE_SEPARATOR, "!include    .Test2Page   ",
				PageParser.LINE_SEPARATOR, "|with cubetools|",
				"|write|10|files of size|10KB|using|10|threads|"));

		assertEquals(3, elements.size());
		assertEquals(PageElementType.INCLUDE.getKey(), elements.get(1)
				.getType().getKey());
		Include include = (Include) elements.get(1);
		assertEquals(".Test2Page", include.getPath());
	}

	@Test
	public void testParseTable() {
		Table first = m_parser.parseTable(CollectionUtils
				.list("|enable advanced retention on clusters|"));
		Table second = m_parser.parseTable(CollectionUtils.list(
				"|with cubetools|",
				"|write|10|files of size|10KB|using|10|threads|"));
		checkTables(first, second);
	}

	@Test
	public void testCreateTable() {
		Table first = m_parser.createTable(TableStyle.UNKNOWN_FIXTURE,
				"enable advanced retention on clusters");
		Table second = m_parser.createTable(TableStyle.UNKNOWN_FIXTURE,
				"with cubetools", PageParser.LINE_SEPARATOR, "write", "10",
				"files of size", "10KB", "using", "10", "threads");
		checkTables(first, second);
	}

	public void checkPage(Page page) {
		assertEquals(2, page.getElements().size());
	}

	public void checkTables(Table first, Table second) {
		assertEquals(TableStyle.UNKNOWN_FIXTURE, first.getStyle());
		assertEquals(1, first.getData().size());
		assertEquals(1, first.getData().get(0).size());
		assertEquals("enable advanced retention on clusters", StringUtils.join(
				first.getData().get(0), "|"));

		assertEquals(TableStyle.UNKNOWN_FIXTURE, second.getStyle());
		assertEquals(2, second.getData().size());
		assertEquals("with cubetools", StringUtils.join(
				second.getData().get(0), "|"));
		assertEquals("write|10|files of size|10KB|using|10|threads",
				StringUtils.join(second.getData().get(1), "|"));

	}
}
